package com.iflytek.cosmo.ocr.common.util;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import com.iflytek.cosmo.ocr.common.constant.CommonConstant;


import cn.hutool.core.lang.UUID;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * 文件工具类
 *
 */
@SuppressWarnings("restriction")
public class FileUtil {
	
	/**
	 * inputStream转换成ByteArray
	 * @param inStream
	 * @return
	 * @throws Exception
	 */
	public static byte[] inputStream2ByteArray(InputStream inStream) throws Exception {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100]; //buff用于存放循环读取的临时数据
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] in_b = swapStream.toByteArray(); //in_b为转换之后的结果
        return in_b;
    }

	/**
	 * MultipartFile 转换成 File
	 * @param multipartFile multipartFile文件
	 * @return File文件
	 */
	public static File multipartToFile(MultipartFile multipartFile) {
		File file = null;
		try {
			file = File.createTempFile("tmpFile", null);
			multipartFile.transferTo(file);
		} catch (IOException e) {
		    e.printStackTrace();
		}
		return file;
	}
	
	/**
	 * 删除文件
	 * @param file 文件
	 */
	public static void deleteFile(File file){
		if(file != null){
			file.delete();
		}
	}
	
	/**
	 * byte[]转换成string
	 * @param bytes 数据内容
	 * @return string字符串
	 * @throws Exception Exception
	 */
	public static String byteToStr(byte[] bytes) throws Exception{
		String str = StringUtils.EMPTY;
    	String fileCode = EncodingDetect.getJavaEncode(bytes);
		str = new String(bytes, fileCode);
		return str;
	}

	/**
	 * byte[]转换成file
	 * @param bytes byte[]内容
	 * @param filePath 文件路径
	 * @param fileName 文件名
	 * @return 文件
	 */
	public static File byteToFile(byte[] bytes, String filePath, String fileName) {
		BufferedOutputStream bos = null;
		FileOutputStream fos = null;
		File file = null;
		try {
			File dir = new File(filePath);
			if (!dir.exists() && dir.isDirectory()) {
				dir.mkdirs();
			}
			file = new File(filePath + File.separator + fileName);
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos);
			bos.write(bytes);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return file;
	}
	
	/**
	 * file转换成byte[]
	 * @param file 文件
	 * @return byte[]内容
	 */
	public static byte[] fileToByte(File file) {
		byte[] buffer = null;
		try {
			FileInputStream fis = new FileInputStream(file);
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			byte[] b = new byte[1024];
			int n;
			while ((n = fis.read(b)) != -1) {
				bos.write(b, 0, n);
			}
			fis.close();
			bos.close();
			buffer = bos.toByteArray();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return buffer;
	}

    /**
     * 上传的文件是否是合法的图片文件
     *
     * @param fileName 文件名
     *
     * @return true: 该文件格式是允许上传的图片格式之一
     */
    public static boolean isValidUploadPic(String fileName) {
        return StringUtils.isNotBlank(fileName) && CommonConstant.VALID_UPLOAD_PIC_SUFFIX
                .contains(StringUtils.substringAfterLast(fileName, ".").toLowerCase());
    }

    /**
     * 上传的文件是否是合法的文件
     *
     * @param fileName 文件名
     *
     * @return true: 该文件格式是允许上传的图片格式之一
     */
    public static boolean isValidUploadFile(String fileName) {
        return StringUtils.isNotBlank(fileName) && CommonConstant.VALID_UPLOAD_FILE_SUFFIX
                .contains(StringUtils.substringAfterLast(fileName, ".").toLowerCase());
    }

    /**
     * <p>文件后缀名是否匹配(不区分大小写)</p>
     *
     * <pre>
     * FileUtil.isSuffixEqualsIngnoreCase(null, *)    = false
     * FileUtil.isSuffixEqualsIngnoreCase("", *)      = false
     * FileUtil.isSuffixEqualsIngnoreCase("  ", *)    = false
     * FileUtil.isSuffixEqualsIngnoreCase(*, null)    = false
     * FileUtil.isSuffixEqualsIngnoreCase(*, "")      = false
     * FileUtil.isSuffixEqualsIngnoreCase(*, "  ")    = false
     * FileUtil.isSuffixEqualsIngnoreCase("test.doc", "doc")      = true
     * FileUtil.isSuffixEqualsIngnoreCase("test.doc", "Doc")      = true
     * FileUtil.isSuffixEqualsIngnoreCase("test.Doc", "doc")      = true
     * FileUtil.isSuffixEqualsIngnoreCase("test.DOC", "DoC")      = true
     * FileUtil.isSuffixEqualsIngnoreCase("testdoc", "doc")       = false
     * FileUtil.isSuffixEqualsIngnoreCase("testDOC", "doc")       = false
     * </pre>
     *
     * @param fileName 文件名
     * @param suffix   后缀名
     *
     * @return
     */
    public static boolean isSuffixEqualsIngnoreCase(String fileName, String suffix) {
        if (StringUtils.isBlank(fileName) || StringUtils.isBlank(suffix)) {
            return false;
        }
        return StringUtils.endsWithIgnoreCase(fileName, '.' + suffix);
    }
    /**
     * 多个pdf word合并导出
     * <br>
     * 适用场景:	<br>
     * 调用方式:	<br>
     * 业务逻辑说明<br>
     *
     * @param list
     * @param type
     * @param mergeFileName
     * @return
     * @throws Exception
     * @autho dgyu
     * @time 2019年10月15日 下午3:15:58
     */
	@SuppressWarnings("deprecation")
	public static byte[] mergePDFByByte(List<byte[]> list, String type,String mergeFileName) throws Exception {
		   String folder = System.getProperty("java.io.tmpdir");
		   String destinationFileName = mergeFileName;
		   PDFMergerUtility mergePdf = new PDFMergerUtility();
		   List<File> tempFiles=new ArrayList<>();
		   for (byte[] data : list) {
		      String fileNameUuid = UUID.randomUUID().toString() + "." + type;
		      File file = new File(folder + File.separator + fileNameUuid);
		      //file.deleteOnExit();
		      FileOutputStream fileOutputStream = new FileOutputStream(file);
		      fileOutputStream.write(data);
		      fileOutputStream.close();
		      tempFiles.add(file);

		      mergePdf.addSource(folder + File.separator + fileNameUuid);
		   }
		   mergePdf.setDestinationFileName(folder + File.separator + destinationFileName);
		   mergePdf.mergeDocuments();

		   File file = new File(folder + File.separator + destinationFileName);
		   //file.deleteOnExit();
		   FileInputStream fis = new FileInputStream(file);
		   ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
		   byte[] b = new byte[1000];
		   int n;
		   while ((n = fis.read(b)) != -1) {
		      bos.write(b, 0, n);
		   }
		   fis.close();
		   byte[] data = bos.toByteArray();
		   bos.close();
		   for(File tempFile:tempFiles){
		      FileUtils.deleteQuietly(tempFile);
		   }
		   FileUtils.deleteQuietly(file);
		   return data;
		}
	
	/**
	 * 合并导出word文档
	 * <br>
	 * 适用场景:	<br>
	 * 调用方式:	<br>
	 * 业务逻辑说明<br>
	 *
	 * @param list
	 * @param type
	 * @param mergeFileName
	 * @return
	 * @throws Exception
	 * @autho dgyu
	 * @time 2019年10月15日 下午4:25:53
	 */
	public static byte[] mergeDocByByte(List<byte[]> list, String type,
			String mergeFileName) throws Exception {
		String folder = System.getProperty("java.io.tmpdir");
		String destinationFileName = mergeFileName;
		List<String> files = new ArrayList<>();
		for (byte[] data : list) {
			String fileNameUuid = UUID.randomUUID().toString() + "." + type;
			String tempFileFullPath = folder + File.separator + fileNameUuid;
			File file = new File(tempFileFullPath);
			file.deleteOnExit();
			FileOutputStream fileOutputStream = new FileOutputStream(file);
			fileOutputStream.write(data);
			fileOutputStream.close();
			files.add(tempFileFullPath);
		}

		/**
		 * 合并word操作
		 */
		InputStream in1 = null;
		InputStream in2 = null;
		OPCPackage src1Package = null;
		OPCPackage src2Package = null;
		OutputStream dest = new FileOutputStream(
				folder + File.separator + destinationFileName);
		in1 = new FileInputStream(files.get(0));
		src1Package = OPCPackage.open(in1);
		XWPFDocument src1Document = new XWPFDocument(src1Package);
		CTBody src1Body = src1Document.getDocument().getBody();

		for (int i = 1; i < files.size(); i++) {
			XWPFParagraph p = src1Document.createParagraph();
			in2 = new FileInputStream(files.get(i));
			src2Package = OPCPackage.open(in2);
			// 设置分页符
			p.setPageBreak(true);
			XWPFDocument src2Document = new XWPFDocument(src2Package);
			CTBody src2Body = src2Document.getDocument().getBody();
			appendBody(src1Body, src2Body);
			new File(files.get(i)).delete();
			src2Document.close();
			in2.close();
		}
		src1Document.write(dest);
		src1Document.close();
		in1.close();
		dest.close();

		File file = new File(folder + File.separator + destinationFileName);
		file.deleteOnExit();
		FileInputStream fis = new FileInputStream(file);
		ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
		byte[] b = new byte[1000];
		int n;
		while ((n = fis.read(b)) != -1) {
			bos.write(b, 0, n);
		}
		fis.close();
		byte[] data = bos.toByteArray();
		bos.close();
		return data;
	}
	
	
	
	/**
	 * 合并文档内容
	 * @param src 目标文档
	 * @param append 要合并的文档
	 * @throws Exception
	 */
	private static void appendBody(CTBody src, CTBody append) throws Exception {
		XmlOptions optionsOuter = new XmlOptions();
		optionsOuter.setSaveOuter();
		String appendString = append.xmlText(optionsOuter);
		String srcString = src.xmlText();
		String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
		String mainPart = srcString.substring(srcString.indexOf(">") + 1,
				srcString.lastIndexOf("<"));
		String sufix = srcString.substring(srcString.lastIndexOf("<"));
		String addPart = appendString.substring(appendString.indexOf(">") + 1,
				appendString.lastIndexOf("<"));
		CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart
				+ sufix);
		src.set(makeBody);
	}
	
	//base64字符串转byte[]
	public static byte[] base64String2ByteFun(String base64Str) throws IOException{
        return new BASE64Decoder().decodeBuffer(base64Str);
    }
    //byte[]转base64
	public static String byte2Base64StringFun(byte[] b){
        return new BASE64Encoder().encode(b);
    }
}
